<template>
	<view @longpress="" @touchstart="touchStart" @touchmove.stop.prevent="touchMove" @touchend="touchEnd"
		@touchcancel="touchEnd" @mousedown="touchStart" @mousemove.stop.prevent="touchMove" @mouseup="touchEnd"
		@mouseleave="touchEnd" class="relative overflow"
		:style="[{ width: `${view_width}px`, height: `${view_height}px`, background: '#000000' }]">
		<view v-if="!url" class="flex flex-center py-24"><text style="font-size: 24rpx;color: white;">请选择选择图片才可操作</text>
		</view>
		<!-- #ifndef APP-NVUE -->
		<canvas id="imgid" canvas-id="imgid" class=" l-0 t-0" :style="[
			{ 
				width: `${rectPos.w}px`, 
				height: `${rectPos.h}px`,
				transform: `translate(-1000px,-1000px)`,
			}
			]">
		</canvas>
		<!-- #endif -->
		<!-- transform: `translate(${imgPos.x}px,${imgPos.y}px) scale(${imgPos.scale},${imgPos.scale})` -->
		<!-- <image v-if="url" :src="url"></image> -->
		<image v-if="url" @error="imgError" class="absolute l-0 t-0" :class="[moveable?'opacity-10':'ani opacity-5']"
			:userInteractionEnabled="false" @load="imgLoad" :src="url" :style="[
		{
		  width: `${imgPos.w||1}px`,
		  height: `${imgPos.h||1}px`,
		  transform: url?`translate(${imgPos.x}px,${imgPos.y}px) scale(${imgPos.scale},${imgPos.scale})`:`translate(-1000px,-1000px)`,
		  'transform-origin': `${imgPos.center[0]}px ${imgPos.center[1]}px`
		}
	]"></image>
		<!-- 		   -->
		<view :class="[moveable?'':'ani']" :userInteractionEnabled="false" class="absolute l-0 t-0 rect" :style="[
      { width: rectPos.w + 'px', height: rectPos.h + 'px', transform: `translate(${rectPos.x}px,${rectPos.y}px)` }
    ]">

		</view>

		<view class="absolute l-0 b-0" :style="{ width: `${view_width}px`, height: `${80}px` }">
			<!-- 	<view class="flex-center mb-24">
				<tm-slider @change="scaleChange" :width="600" :max='3' :min='1'></tm-slider>
			</view> -->
			<view class="flex-row flex flex-row-center-between">
				<!-- 翻转 -->
				<!-- <view class="flex-1 flex flex-center">
					<tm-text :userInteractionEnabled="false" color="white" label="旋转"></tm-text>
				</view> -->
				<!-- 取消 -->
				<view @click="emits('cance')" class="flex-1 flex flex-center">
					<tm-text :userInteractionEnabled="false" color="white" label="取消"></tm-text>
				</view>
				<!-- 选择图片 -->
				<view @click="chooseImg" class="flex-1 flex flex-center">
					<tm-text :userInteractionEnabled="false" color="white" label="选择图片"></tm-text>
				</view>
				<!-- 确认 -->
				<view @click="pushImgToCanvas" class="flex-1 flex flex-center">
					<tm-text  :userInteractionEnabled="false" color="white" label="确认"></tm-text>
				</view>
			</view>
		</view>
	</view>
</template>

<script lang="ts" setup>
	/**
	 * 图片裁剪
	 * @description nvue平台暂时未实现，你可以把本组件放置到vue页面来使用。
	 * @description 因为uniapp平台，暂不支持在nvue页面上canvas上渲染本地路径图片，只支持远程，暂时搁置，另想plugs方法来实现。
	 * 
	 */
	import {
		ref,getCurrentInstance,onMounted,nextTick
	} from "vue"
	import tmIcon from "../tm-icon/tm-icon.vue";
	import tmText from "../tm-text/tm-text.vue";
	import tmSlider from "../tm-slider/tm-slider.vue"
	const proxy = getCurrentInstance()?.proxy??null;
	const emits = defineEmits(["confirm","cance"])
	const props = defineProps({
		url: {
			type: String,
			default: ''
		},
		width:{
			type:Number,
			default:150
		},
		height:{
			type:Number,
			default:150
		}
	})
	//当前需要裁剪图片的地址。注意，如果不提供则需要选择对应的图片。
	const url = ref(props.url)
	const {
		safeArea,
		windowWidth,
		windowHeight,
		statusBarHeight
	} = uni.getSystemInfoSync()
	// 视窗的宽。
	const view_width = safeArea?.width || windowWidth;
	//视窗的高度。
	let view_height = safeArea?.height??windowHeight - 44;
	// #ifdef MP
	view_height = safeArea?.height??windowHeight;
	// #endif
	//手指触摸的坐标点。
	const points = ref({
		px: 0, //手指触摸是的1指坐标x
		py: 0, //手指触摸是的1指坐标y
		px2: 0, //手指触摸是的2指坐标x
		py2: 0, //手指触摸是的2指坐标y
		xy: 0, //两指间的距离.
	})
	//裁剪框的位置。和宽高。
	const rectPos = ref({
		w: props.width, //当前裁剪框的宽和高
		h: props.height,
		x: 0, //当前坐标
		y: 0
	})
	const imgPos = ref({
		scale: 1, //当前绽放比例
		oldscale: 1,
		center: [0, 0],
		sourceImgWidth: 0, //原始图像的宽和高
		sourceImgHeight: 0,
		w: 0, //缩放后的宽和高
		h: 0,
		x: 0, //当前的坐标。
		y: 0
	})
	let moveable = ref(false);
	let moveType = 0; //0为图片的移动。1为裁剪框的移动。
	let scaleing = ref(false); //是否处于双指缩放中。
	let ctx = null;
	onMounted(() => {
		nextTick(function () {
			setTimeout(function () {
				// #ifndef APP-NVUE
				ctx = uni.createCanvasContext('imgid',proxy)
				// #endif
			}, 50)
		})
	})
	setRectPos()
	function touchStart(res: TouchEvent) {

		if (!url.value) return;
		moveable.value = true;
		let event = res.touches[0];
		let event2 = res.touches[1];
		if (res.type == 'mousedown') {
			event = res;
		}
		moveType = getMoveTypeNumber(event.pageX, event.pageY);

		if (moveType == 0) {
			points.value.px = event.pageX - imgPos.value.x
			points.value.py = event.pageY - imgPos.value.y
		} else {
			points.value.px = event.pageX - rectPos.value.x
			points.value.py = event.pageY - rectPos.value.y

		}

		if (event2) {
			points.value.px2 = event2.pageX
			points.value.py2 = event2.pageY
		}

		imgPos.value.oldscale = imgPos.value.scale
	}

	function touchMove(res: TouchEvent) {
		if(!url.value) {
			return;
		}
		let event = res.touches[0];
		let event2 = res.touches[1];
		if (res.type == 'mousedown') {
			event = res;
		}
		if (!moveable.value) return;
		if (moveType == 0) {
			imgPos.value.x = event.pageX - points.value.px
			imgPos.value.y = event.pageY - points.value.py
		} else {

			rectPos.value.x = event.pageX - points.value.px
			rectPos.value.y = event.pageY - points.value.py
		}



		//双向缩放暂时不实现。
		return;
		// points.value.px = event.pageX - points.value.px
		// points.value.py = event.pageY -  points.value.py
		if (event2) {

			scaleing.value = true;
			points.value.px2 = event2.pageX
			points.value.py2 = event2.pageY

			// 双指缩放比例计算
			var zoom = getDistance({
					x: event.pageX,
					y: event.pageY
				}, {
					x: event2.pageX,
					y: event2.pageY
				}) /
				getDistance({
					x: points.value.px,
					y: points.value.py
				}, {
					x: points.value.px2,
					y: points.value.py2
				});
			var newScale = imgPos.value.oldscale * zoom;


			var newscale = imgPos.value.oldscale * zoom;

			imgPos.value.scale = newscale
			const center = getScaleCenter({
				x: event.pageX,
				y: event.pageY
			}, {
				x: event2.pageX,
				y: event2.pageY
			})
			imgPos.value.x = center[0] - imgPos.value.center[0]
			imgPos.value.y = center[1] - imgPos.value.center[1]
			// imgPos.value.w = newscale*imgPos.value.w
			// imgPos.value.h = newscale*imgPos.value.h
		} else {
			if (scaleing.value) return;
			if (moveType == 0) {
				imgPos.value.x = event.pageX - points.value.px
				imgPos.value.y = event.pageY - points.value.py
			} else {

				rectPos.value.x = event.pageX - points.value.px
				rectPos.value.y = event.pageY - points.value.py
			}
		}

	}

	function touchEnd(res: Event) {
		if(!url.value) {
			return;
		}
		moveable.value = false;
		scaleing.value = false;

		if (rectPos.value.x <= 12) {
			rectPos.value.x = 12;
		}
		if (rectPos.value.x >= view_width - rectPos.value.w - 12) {
			rectPos.value.x = view_width - rectPos.value.w - 12;
		}

		if (rectPos.value.y <= 12) {
			rectPos.value.y = 12;
		}

		if (rectPos.value.y >= view_height - rectPos.value.h - 90) {
			rectPos.value.y = view_height - rectPos.value.h - 90;
		}


		if (imgPos.value.x >= rectPos.value.x) {
			imgPos.value.x = rectPos.value.x
		}
		if (imgPos.value.x + imgPos.value.w <= rectPos.value.x + rectPos.value.w) {
			imgPos.value.x = rectPos.value.x - (imgPos.value.w - rectPos.value.w)
		}
		if (imgPos.value.y >= rectPos.value.y) {
			imgPos.value.y = rectPos.value.y
		}
		if (imgPos.value.y + imgPos.value.h <= rectPos.value.y + rectPos.value.h) {
			imgPos.value.y = rectPos.value.y - (imgPos.value.h - rectPos.value.h)
		}
	}

	function chooseImg() {
		uni.chooseImage({
			count: 1,
			success(res) {

				let files = res.tempFilePaths;
				if (files.length == 1) {
					url.value = files[0];
					imgPos.value.scale = 1
					imgPos.value.oldscale = 1
				}
			}
		})
	}

	function scaleChange(scale: number) {
		scale = scale > 1 ? scale - 0.5 : scale
		if (scale == imgPos.value.scale) return;
		imgPos.value.scale = scale
		imgPos.value.h = rectPos.value.h * scale
		imgPos.value.w = rectPos.value.w * scale
		// setImgPosScaleXy()
		if (scale == 1) {
			setImgPosScaleXy()
		}
	}

	function imgLoad(res: Event) {
		const {
			width,
			height
		} = res.detail;
		imgPos.value.sourceImgWidth = width;
		imgPos.value.sourceImgHeight = height;

		setImgPosScaleXy()
	}

	function imgError(res) {
		console.log(res)
	}
	//设置当前移动的类型，应该移动哪个。0移动图片，1矩形。
	function getMoveTypeNumber(x: number, y: number) {
		if (x >= rectPos.value.x - 15 && x <= rectPos.value.x + 15 && y >= rectPos.value.y && y <= rectPos.value.y +
			rectPos.value.h

		) {
			return 1;
		}
		if (x >= rectPos.value.x && x <= rectPos.value.w && y >= rectPos.value.y - 15 && y <= rectPos.value.y + 15) {
			return 1;
		}
		if (x >= rectPos.value.x + rectPos.value.w - 15 && x <= rectPos.value.x + rectPos.value.w + 15 && y >= rectPos
			.value.y && y <= rectPos.value.y + rectPos.value.h) {
			return 1;
		}
		if (x >= rectPos.value.x && x <= rectPos.value.x + rectPos.value.w && y >= rectPos.value.y + rectPos.value.h -
			15 && y <= rectPos.value.y + rectPos.value.h + 15) {
			return 1;
		}
		return 0
	}
	var getDistance = function(start, stop) {
		return Math.hypot(stop.x - start.x, stop.y - start.y);
	};
	var getScaleCenter = function(start, stop) {
		let minx = (stop.x + start.x) / 2
		let miny = (stop.y + start.y) / 2
		return [minx, miny];
	};

	///设置剪裁框的坐标。
	function setRectPos() {
		let x = (view_width - rectPos.value.w) / 2;
		let y = (view_height - rectPos.value.h) / 2;
		rectPos.value.x = x;
		rectPos.value.y = y;
	}
	//设置当前图片的位置和宽高。
	function setImgPosScaleXy() {
		imgPos.value.x = rectPos.value.x
		let now_w = rectPos.value.w
		let now_h = now_w / (imgPos.value.sourceImgWidth / imgPos.value.sourceImgHeight);
		imgPos.value.h = now_h
		imgPos.value.w = now_w


		//如果高度不够。需要放大。
		if (imgPos.value.h < rectPos.value.h) {
			imgPos.value.h = rectPos.value.h
			//计算下倍数。

			imgPos.value.w = imgPos.value.h * (now_w / now_h)
		}
		imgPos.value.y = -(imgPos.value.h - rectPos.value.h) / 2 + rectPos.value.y
		imgPos.value.center = [imgPos.value.w / 2, imgPos.value.h / 2]

	}
	
	function pushImgToCanvas(){
		if(!url.value) {
			uni.showToast({
				title:"未选择",
				icon:"none"
			})
			return;
		}
		let dx = Math.abs(imgPos.value.x - rectPos.value.x)
		let dy = Math.abs(imgPos.value.y - rectPos.value.y)
		// #ifndef APP-NVUE
		ctx.drawImage(url.value, -dx, -dy,imgPos.value.w,imgPos.value.h)
		ctx.draw(false,(res)=>{
			console.log("绘制成功 ")
			uni.canvasToTempFilePath({
				canvasId:'imgid',
				success(ok) {
					// h5为base64 
					emits("confirm",ok.tempFilePath)
				}
			},proxy)
		})
		
		// #endif
		// #ifdef APP-NVUE
		// ctx.drawImage(url.value, -dx, -dy,imgPos.value.w,imgPos.value.h)
		// 因为在nvue上,uniapp有bug，不能绘制本地路径的图片，因此曲线救国。
		// #endif
	}

</script>

<style scoped>
	.rect {
		border: 1px solid #FFFFFF;
	}

	.ani {
		/* #ifndef APP-NVUE */
		transition-duration: 0.3s;
		/* #endif */
		transition-property: transform;
		transition-timing-function: ease;

	}
</style>
